﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Compression;
using System.Xml.Linq;

namespace DimensionAddIn.V2
{
    public class XTemplate
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public List<XDRow> YRows { get; set; }
        public List<XDRow> XRows { get; set; }

        public List<XDim> YDims { get; set; }
        public List<XDim> XDims { get; set; }

        public XTemplate()
        {
            YRows = new List<XDRow>();
            XRows = new List<XDRow>();

            YDims = new List<XDim>();
            XDims = new List<XDim>();
        }

        public static XTemplate Deserialize(string data1, string data2, string data3)
        {
            XTemplate xTemplate = new XTemplate();

            byte[] data1Arr = Convert.FromBase64String(data1);
            data1Arr = Decompress(data1Arr);
            string xmlData1 = Encoding.UTF8.GetString(data1Arr);
            byte[] data2Arr = Convert.FromBase64String(data2);
            data2Arr = Decompress(data2Arr);
            string xmlData2 = Encoding.UTF8.GetString(data2Arr);
            byte[] data3Arr = Convert.FromBase64String(data3);
            data3Arr = Decompress(data3Arr);
            string xmlData3 = Encoding.UTF8.GetString(data3Arr);

            XDocument xDoc1 = XDocument.Parse(xmlData1);
            XDocument xYRowDoc = XDocument.Parse(xmlData2);
            XDocument xXRowDoc = XDocument.Parse(xmlData3);

            xTemplate.Id = new Guid(xDoc1.Element("doc").Attribute("id").Value);
            xTemplate.Name = xDoc1.Element("doc").Attribute("name").Value;
            IEnumerable<XElement> xyDims = xDoc1.Element("doc").Element("yd").Elements("i");
            foreach (var xDim in xyDims)
            {
                string code = xDim.Attribute("c").Value;
                string name = xDim.Attribute("n").Value;
                int index = Convert.ToInt32(xDim.Attribute("i").Value);
                int dirIndex = Convert.ToInt32(xDim.Attribute("di").Value);
                bool isPageDim = Convert.ToBoolean(xDim.Attribute("p").Value);
                XDim dim = new XDim();
                dim.Code = code;
                dim.Name = name;
                dim.Index = index;
                dim.DirIndex = dirIndex;
                xTemplate.YDims.Add(dim);
            }
            IEnumerable<XElement> xxDims = xDoc1.Element("doc").Element("xd").Elements("i");
            foreach (var xDim in xxDims)
            {
                string code = xDim.Attribute("c").Value;
                string name = xDim.Attribute("n").Value;
                int index = Convert.ToInt32(xDim.Attribute("i").Value);
                int dirIndex = Convert.ToInt32(xDim.Attribute("di").Value);
                bool isPageDim = Convert.ToBoolean(xDim.Attribute("p").Value);
                XDim dim = new XDim();
                dim.Code = code;
                dim.Name = name;
                dim.Index = index;
                dim.DirIndex = dirIndex;
                xTemplate.XDims.Add(dim);
            }

            #region y-rows
            IEnumerable<XElement> xYRows = xYRowDoc.Element("y").Elements("d");
            foreach (var xYRow in xYRows)
            {
                XDRow row = new XDRow();
                IList<XElement> xYItems = xYRow.Elements("i").ToList();
                row.Items = new XDItem[xYItems.Count];
                for (int index = 0; index < row.Items.Length; index++)
                {
                    var xYItem = xYItems[index];

                    int level = Convert.ToInt32(xYItem.Attribute("l").Value);
                    string code = xYItem.Attribute("c").Value;
                    string name = xYItem.Attribute("n").Value;

                    XDItem item = new XDItem();
                    item.Level = level;
                    item.Code = code;
                    item.Name = name;
                    row.Items[index] = item;
                }
                xTemplate.YRows.Add(row);
            }
            #endregion

            IEnumerable<XElement> xXRows = xXRowDoc.Element("x").Elements("d");
            foreach (var xXRow in xXRows)
            {
                XDRow row = new XDRow();
                IList<XElement> xXItems = xXRow.Elements("i").ToList();
                row.Items = new XDItem[xXItems.Count];
                for (int index = 0; index < row.Items.Length; index++)
                {
                    var xYItem = xXItems[index];

                    int level = Convert.ToInt32(xYItem.Attribute("l").Value);
                    string code = xYItem.Attribute("c").Value;
                    string name = xYItem.Attribute("n").Value;

                    XDItem item = new XDItem();
                    item.Level = level;
                    item.Code = code;
                    item.Name = name;
                    row.Items[index] = item;
                }
                xTemplate.XRows.Add(row);
            }

            return xTemplate;
        }

        private static byte[] Decompress(byte[] bytes)
        {
            using (MemoryStream tempMs = new MemoryStream())
            {
                using (MemoryStream ms = new MemoryStream(bytes))
                {
                    GZipStream Compress = new GZipStream(ms, CompressionMode.Decompress);

                    Compress.CopyTo(tempMs);
                    Compress.Close();

                    return tempMs.ToArray();
                }
            }
        }
    }
}
